home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_11_01
/
1101046a
< prev
next >
Wrap
Text File
|
1992-11-07
|
16KB
|
580 lines
#if !defined TSTREAM_H
#define TSTREAM_H
#include <iostream.h> // for base class definitions
// class tbuf<>. Derived publicly from streambuf to
// allow class ios which contains pointer to streambuf
// access to virtual functions. tbuf<> implements
// basic buffering, reading, writing and seeking on
// a stream. It also provides open, close, attach,
// and utility functions.
template <class T>
class tbuf : public streambuf {
public:
// openProtection provides a default parameter to the
// open functions to specify what protection a file
// will be created with. You can ignore this if it is
// not necessary
static const int openProtect;
// tbufSize specifies the default buffer size. It is
// set to 516 bytes.
static const int tbufSize;
// Default contructor. Make a buffer without a
// stream attached. mode has a dual meaning, if it
// is zero it means that any operation is allowable,
// and the stream should not be deleted when closing.
tbuf()
: stream(0), mode(0), opened(0)
{
makbuf();
}
// create buffer and attach to t. t is assumed to be
// already opened in read/write mode. t will not be
// deleted or closed when closing this buffer
tbuf(T &t)
: stream(&t), mode(0), opened(1)
{
makbuf();
}
// create buffer from parameters, and attach to t.
tbuf(T &t, char* b, int l)
: stream(&t), mode(0), opened(1)
{
setbuf(b, l);
}
// destroy buffer. If mode is not zero, t will be
// closed and deleted. Otherwise just flush the
// output buffer.
~tbuf()
{
if(mode)
close();
else
overflow(EOF);
}
// return open status
int is_open() const
{
return opened;
}
// return reference to stream
T &fd() const
{
return *stream;
}
// open stream. mode must not be zero. stream will
// be closed and deleted when closing buffer.
tbuf *open(const char *name, int mode,
int prot = tbuf::openProtect);
// close buffer and optionally delete stream.
tbuf *close();
// attach stream to buffer. Stream is assumed to
// be opened in read/write mode.
tbuf *attach(T &);
// write buffer to stream and reset pointers.
virtual int overflow(int = EOF);
// read data into buffer and reset pointers.
virtual int underflow();
// sync input and output.
virtual int sync();
// seek to offset and flush output buffers.
virtual long seekoff(long, ios::seek_dir, int);
// set buffer. For unbuffered i/o set char * to 0.
virtual streambuf *setbuf(char *, int);
protected:
int putBackSize()
{
return (blen() > 8) ? 4 : 1;
}
void resetpg(int end = 0);
void makbuf()
{
setbuf(new char[tbufSize], tbufSize);
}
int unbuffered()
{
return streambuf::unbuffered() | !base();
}
T *stream;
int mode;
short opened;
char lookAhead[2];
};
template <class T>
const int tbuf<T>::tbufSize = 516;
template <class T>
const int tbuf<T>::openProtect = 0;
// Attach an open stream to this buffer. When this
// buffer is closed don't try to close stream. If
// not yet buffered, try to create a buffer. Reset
// the put and get pointers. Return 0 on error, or
// this if OK.
template <class T>
tbuf<T>* tbuf<T>::attach(T &t)
{
if(opened) // if already opened, return 0
return 0;
stream = &t; // attach stream.
opened = 1; // set to opened.
mode = 0; // buffer doesn't own stream.
if(!base()) // if no buffer yet...
makbuf(); // try to make one.
else
resetpg(); // reset put and get pointers.
return this;
}
// Close buffer, and optionally stream attached to it.
// Flush buffer if data inside. Return 0 on error or
// this if OK.
template <class T>
tbuf<T>* tbuf<T>::close()
{
if(!*stream) // if stream closed,
opened = 0; // set opened off.
if(!opened) // if not on return 0.
return 0;
int ret = 0;
if(out_waiting()) // if output in buffer.
// flush output buffer.
ret = (overflow(EOF) == EOF) ? 1 : 0;
if(mode) // if mode is 0, don't
delete stream; // close or delete stream.
opened = 0; // set opened off.
return ret ? 0 : this;
}
// Write data from buffer to stream. This function
// is called when the buffer is full and we need to
// output more characters. The parameter c is the
// character that caused the overflow. If the
// stream is buffered, it will be placed in the
// buffer, otherwise it is written to the stream.
// If input char is EOF, don't write, just flush.
// Returns EOF on error, or 1 on success.
template <class T>
int tbuf<T>::overflow(int c)
{
if(!opened || // check to see if stream
mode == 0 || // is on and mode is out.
!(mode&ios::out))
return EOF;
if(unbuffered())
{
if(c != EOF)
{ // if unbuffered,
char b = c; // write single char
if(stream->write(&b, 1) != 1)
return EOF;
}
}
else // else if buffered.
{
if(sync() != 0) // sync input and output
return EOF; // when writing
resetpg(1); // reset the put/get pointers
if(c != EOF)
{
sputc(c); // add c to the buffer
gbump(1); // move the get pointer
}
}
return 1; // return OK
}
// Open stream. If mode ios::ate (at end) is on,
// seek to end
template <class T>
tbuf<T>* tbuf<T>::open(const char* n, int m, int p)
{
if(opened || !m) // if already on, or no mode,
return 0; // return error.
stream = new T; // make new stream pointer.
stream->open(n, m, p);// open stream.
if(!*stream) // if stream not open,
return 0; // return error.
opened = 1; // set to on.
mode = m; // remeber mode.
if((mode & ios::ate) &&
stream->seek(0L, ios::end) == EOF)
return 0; // seek to end if ios::ate.
resetpg(); // reset put/get pointers.
return this; // return OK.
}
// Set the buffer, reset the put/get pointers.
// Return 0 on error, this if OK.
template <class T>
streambuf* tbuf<T>::setbuf(char* b, int l)
{
if(!b) // turn off buffering.
{
streambuf::unbuffered(1);
return this;
}
if(opened && base())// check if stream is opened,
return 0; // , and no buffer yet.
setb(b, b+l, 0); // set buffer pointers.
resetpg(); // reset put/get pointers.
return this; // return OK.
}
// Seek to offset. dir indicates the relativity of
// the offset, ethier from beginning, current postion,
// or end (ios::beg, ios::cur, ios::end).
// First make sure there's nothing in the buffer.
template <class T>
long tbuf<T>::seekoff(long off, ios::seek_dir dir,
int /* mode ignored */)
{
long loff = off;
int count = out_waiting(); // flush output first.
if(count)
{
if(stream->write(pbase(), count) != count)
return EOF;
}
else if(dir == ios::cur && // if relative seek,
(count = in_avail()) != 0)
loff -= count; // discount input.
resetpg(); // reset pointers.
return stream->seek(loff, dir);
}
// sync input and output buffer pointers. If output
// is waiting, write it, if input is waiting,
// back up to read it again
template <class T>
int tbuf<T>::sync()
{
if (!opened) // check if opened.
return EOF;
int count = out_waiting(); // check for output,
if(count) // in buffer.
{
if(stream->write(pbase(), count) != count)
return EOF; // write output.
resetpg(1);
}
else if(in_avail()) // check for input
{ // in buffer
long pos = stream->seek(long(-in_avail()),